function opts(desc)
  M = { noremap = true, silent = true }
  M.desc = desc
  return M
end

function remove_trail_spaces()
  local save_op = vim.api.nvim_win_get_cursor(0)
  vim.cmd([[%s/ \+$//e]])
  vim.cmd([[nohl]])
  vim.api.nvim_win_set_cursor(0, save_op)
end
------------------------------
--  Normal and visual mode  --
------------------------------
vim.keymap.set('n', ',w', ':w<CR>', opts("save files"))
vim.keymap.set('n', ',q', ':q<CR>', opts("exit buffer"))
vim.keymap.set({'n', 'v'}, 'J', '5j', opts("jump down 5 lines"))
vim.keymap.set({'n', 'v'}, 'K', '5k', opts("jump up 5 lines"))
vim.keymap.set({'n', 'v'}, 'L', '5l', opts("move right by 5 characters"))
vim.keymap.set({'n', 'v'}, 'H', '5h', opts("move left by 5 characters"))
vim.keymap.set({'n', 'v'}, '<C-l>', '<C-w><C-l>', opts("jump to right window"))
vim.keymap.set({'n', 'v'}, '<C-h>', '<C-w><C-h>', opts("jump to left window"))
vim.keymap.set({'n', 'v'}, '<C-j>', '<C-w><C-j>', opts("jump to upper window"))
vim.keymap.set({'n', 'v'}, '<C-k>', '<C-w><C-k>', opts("jump to below window"))
vim.keymap.set('n', '<space>l', ':nohl<CR>', opts("stop the highlighting"))
vim.keymap.set('n', ',ad', ':set autochdir<CR>:set noautochdir<CR>', opts("change the current working directory"))
vim.keymap.set('n', '<space>ds', remove_trail_spaces, opts("remove trailing spaces"))

vim.keymap.set({'n', 'v'}, '{', '<C-e>', opts("scroll down one line"))
vim.keymap.set({'n', 'v'}, '}', '<C-y>', opts("scroll down one line"))

vim.keymap.set('n', 'tn', ':tabnew<CR>', opts("new a tab"))
vim.keymap.set('n', 'th', ':-tabnext<CR>', opts("previous tab"))
vim.keymap.set('n', 'tl', ':+tabnext<CR>', opts("next tab"))

vim.keymap.set({'n', 'x'}, 'ss', 's', opts("delete and insert"))
vim.keymap.set({'n', 'x'}, 'sv', '<C-w>t<C-w>H', opts("place window vertically"))
vim.keymap.set({'n', 'x'}, 'sh', '<C-w>t<C-w>K', opts("place window horizontally"))
-------------------
-- Terminal mode --
-------------------
vim.keymap.set('t', '<C-n>', '<C-\\><C-n>', opts("exit insert mode"))

-------------------
--  visual mode  --
-------------------
-- vim.keymap.set('v', 'Y', '"+y', opts)
vim.keymap.set('v', ',ar', function ()
  vim.api.nvim_command('normal! y')
  local text = vim.fn.getreg('"')
  local reversed = string.reverse(text)
  vim.api.nvim_command('normal! gvc' .. reversed)
end, opts("reverse the selected word"))


